package org.swxjava.assembler.avm1.convert;

import java.util.Map;

import org.swxjava.assembler.Converter;
import org.swxjava.assembler.MarshallException;
import org.swxjava.assembler.ObjectCompiler;
import org.swxjava.assembler.avm1.AsObject;
import org.swxjava.assembler.avm1.AsObjectProperty;
import org.swxjava.assembler.avm1.AsVarString;
import org.swxjava.util.Log;
import org.swxjava.util.LogFactory;

public class MapConverter extends BaseConverter implements Converter {
	
	/** Logger */
    private static final Log LOG = LogFactory.getLog(MapConverter.class);
    
	private boolean sentNonStringWarning = false;
	
	public ObjectCompiler convert(Object data) throws MarshallException {
		return convertMapEntries((Map)data);
	}
		
	protected AsObject convertMapEntries(Map map) throws MarshallException {
		Map.Entry[] entries = (Map.Entry[]) map.entrySet().toArray(new Map.Entry[map.size()]);
		
		AsObject asObj = new AsObject();
		for (int i = (entries.length-1); i >= 0; i--) {
			Map.Entry entry = entries[i];
			Object key = entry.getKey();
			Object value = entry.getValue();
			
			if (!(key instanceof String) && !sentNonStringWarning) {
				LOG.warn("-- ActionScript does not support non string keys. Converting '" + key.getClass().getName() + "' using toString()");
				sentNonStringWarning = true;
			}
			AsVarString propName = null;
			ObjectCompiler propValue = null;
			try {
				propName = new AsVarString(key.toString());
				try {
					propValue = config.convert(value);
	            } catch (Exception ex) {
	            	propValue = config.convert(null);
	                LOG.warn("Failed to convert map member " + key.toString() + ". Conversion error for type: " + value.getClass().getName(), ex);
	            }
	            asObj.add(new AsObjectProperty(propName, propValue));
            } catch (Exception ex) {
                LOG.warn("Failed to convert map key " + key.toString() + ". Conversion error for type: " + key.getClass().getName(), ex);
            }
		}
		return asObj;
	}
}
